const fs = require('fs');

const spawnSync = require('../../common/spawnSync');

const execSync = require('../../common/execSync');

const message = require('../../common/ansi');

const log = require('../../common/log');

const error = require('../../common/error');

/**
 * 获取本地当前分支
 */
function getLocalBranch(cwd) {

    let params = ['branch'];

    let { result, error, stdout, stderr } = spawnSync('git', params, cwd);

    let branch = '';

    if (result) {

        branch = stdout ? stdout.split('\n').filter(item => item.includes('*'))[0].split(' ')[1] : '';

        message.info('获取本地分支 git ' + params.join(' ') + '   -> ' + branch);
        
        log(1, '获取本地分支 git ' + params.join(' ') + '   ' + branch);

    } else {

        message.error(stderr ? stderr : error);

    }

    return { result, error, branch, stderr }
}

/**
 * 拉取最新内容
 */
function pull(cwd) {

    let params = ['pull'];

    let { result, error, stdout, stderr } = spawnSync('git', params, cwd);

    if (result) {

        message.info('拉取分支 git ' + params.join(' '));

        log(1, '拉取分支 git ' + params.join(' ') + '   ');

    } else {

        message.error(stderr ? stderr : error);

    }

    return { result, error, stdout, stderr }

}

/**
 * 推送标签
 * @param {*} tagName 标签名
 */
function pushTag(tagName,cwd) {

    // 删除本地标签和删除远端标签容许失败，因为不确定标签是否已经存在
    let params = [

        ['tag','-d', tagName],

        ['push', 'origin', ':'+tagName],

        ['tag', tagName]

    ]


    let logMsg = ['删除旧标签 git ', '删除远端旧标签 git ', '创建新标签 git ']

    let results = {}

    // let flag = true;

    params.forEach((item, i) => {

        let { result, error, stdout, stderr } = execSync('git '+ item.join(' '), cwd);

        if (!result || stderr) {

            message.error(stderr ? stderr : error);

            return

        }

        message.info(logMsg[i] + item.join(' '));

        log(1, logMsg[i] + item.join(' '));

        results['result' + i + 1] = result;

        results['stdout' + i + 1] = stdout;

    });

    // 推送标签至远端 不容许失败
    let pushOptParams = ['push', 'origin', tagName];

    let { result, error, stdout, stderr } = execSync('git '+ pushOptParams.join(' '), cwd);

    if(!result){

        message.error(stderr ? stderr : error);

    } else {

        message.info('推送标签 git ' + pushOptParams.join(' '));

        log(1, '推送标签 git ' + pushOptParams.join(' '));

    }

    results.isAllDone=result;

    return results;

}

/**
 * 检查 git 环境 账户状态
 */
function check(cwd) {

    let params = ['config', 'user.name'];

    let { result, error, stdout, stderr } = spawnSync('git', params, cwd);

    if (result && stdout) {

        message.info('检查git环境 git '+params.join(' '));

        log(1, '检查git环境 git '+params.join(' '));

    } else {

        message.error(stderr ? stderr : error);

    }

    return { result, error, stdout, stderr }
}

/**
 * 确认当前文件夹下有git仓库
 */
function checkStatus(cwd) {

    let params = ['status'];

    let { result, error, stdout, stderr } = spawnSync('git', params, cwd);

    if (result && stdout) {

        message.info('检查git状态 git '+params.join(' '));

        log(1, '检查git状态 git '+params.join(' '));

    } else {

        message.error(stderr ? stderr : error);

    }

    return { result, error, stdout, stderr }
}

/**
 * 检查版本标签是否存在，顺便确认上一个版本号是否正确
 * @param {*} lastVersionTag 上一个版本标签
 * @param {*} versionTag 新版本标签
 */
function checkVersionTag(lastVersionTag,versionTag,cwd){

    let params = ['log','--pretty=oneline',`${lastVersionTag}...${versionTag}`];

    let { result, error, stdout, stderr } = spawnSync('git', params, cwd);

    if(result){
        
        message.info('检查git标签 git '+params.join(' '));

        log(1, '检查git标签 git '+params.join(' '));

    }else{

        message.error(stderr ? stderr : error);

    }

    return { result, error, stdout, stderr }

}

/**
 * 获取git信息
 * @param {*} cwd 当前工作路径
 */
function gitInfo({lastVersionTag,versionTag},cwd) {

    if (!(check().result && checkStatus().result)) error('git状态错误 程序退出');

    let branchStr = spawnSync('git', ['branch'], cwd).stdout;

    message.info('文件git.js方法->gitInfo->指令 git branch ->输出：' + branchStr);

    log(1, '文件git.js方法->gitInfo->指令 git branch ->输出：' + branchStr);

    let branch = branchStr ? branchStr.split('\n').filter(item => item.includes('*'))[0].split(' ')[1] : '';

    let commitIdStr = spawnSync('git', ['log', '-n1'], cwd).stdout;

    message.info('文件git.js方法->gitInfo->指令 git log -n1 ->输出：' + commitIdStr);

    log(1, '文件git.js方法->gitInfo->指令 git log -n1 ->输出：' + commitIdStr);

    let commitId = commitIdStr ? commitIdStr.split('\n')[0].split(' ')[1] : '';

    let userStr = spawnSync('git', ['config', '--global', '-l'], cwd).stdout;

    message.info('文件git.js方法->gitInfo->指令 git config --global -l ->输出：' + userStr); 

    log(1, '文件git.js方法->gitInfo->指令 git config --global -l ->输出：' + userStr);

    let user = userStr ? userStr.split('\n').filter(item => item.includes('user.name'))[0].split('=')[1] : 'linwb@yeastar.com';

    let oneLineStr = spawnSync('git', ['log', '--pretty=oneline',`${lastVersionTag}...${versionTag}`], cwd).stdout;

    message.info(`文件git.js方法->gitInfo->指令 git log --pretty=oneline ${lastVersionTag}...${versionTag} ->输出：` + oneLineStr);       

    log(1, `文件git.js方法->gitInfo->指令 git log --pretty=oneline ${lastVersionTag}...${versionTag} ->输出：` + oneLineStr);

    let oneLine = oneLineStr ? oneLineStr : '';

    let isNotCommit = spawnSync('git', ['diff'], cwd).stdout ? true : false;

    message.info('文件git.js方法->gitInfo->指令 git diff ->输出：' + isNotCommit); 

    log(1, '文件git.js方法->gitInfo->指令 git diff ->输出：' + isNotCommit);

    return {
        branch,
        commitId,
        user,
        oneLine,
        isNotCommit
    }
}

/**
 * 写入gitInfo文件
 * @param {*} option 写入文件配置对象user git用户名 branch分支名 commitId提交Id filePath 文件路径 version 版本号 md5sum 压缩包的MD5值
 * @param {*} callback 写入完成的回调
 */
function write(option, callback) {

    let { user, branch, commitId, filePath, version, md5sum } = option;

    let content = `compile user: ${user}
compile time: ${new Date().Format('yyyy-MM-dd HH:mm:ss')}
git branch  : ${branch}
git commitid: ${commitId}
version     : ${version}
md5sum      : ${md5sum}`;

    fs.writeFileSync(filePath + '.gitinfo', content);

    message.info('写入gitInfo文件');

    log(1, '写入gitInfo文件');

    option.filePath = filePath + '.gitinfo';

    if (callback instanceof Function) callback(option);

}

/**
 * 推送分支
 */
function push(data,cwd) {

    let params = data || ['push'];

    let { result, error, stdout, stderr } = execSync('git '+ params.join(' '), cwd);

    if (result) {

        message.info('推送分支 git ' + params.join(' '));

        log(1, '推送分支 git ' + params.join(' '));

    } else {

        message.error(stderr ? stderr : error);
    }

    return { result, error, stdout, stderr }

}

/**
 * 追加文件
 */
function add(cwd,addDir='.') {

    let params = ['add', addDir];

    let { result, error, stdout, stderr } = execSync('git ' + params.join(' '), cwd);

    if (result) {

        message.info('追加文件 git ' + params.join(' '));

        log(1, '追加文件 git ' + params.join(' '));

    } else {

        message.error(stderr ? stderr : error);
    }

    return { result, error, stdout, stderr }
}

/**
 * 提交
 * @param {*} msg 提交消息
 */
function commit(msg,cwd) {

    let params = ['commit', '-m', `'${msg}'`];

    let { result, error, stdout, stderr } = execSync('git ' + params.join(' '), cwd);

    if (result) {

        message.info('提交 git ' + params.join(' '));

        log(1, '提交 git ' + params.join(' '));

    } else {

        message.error(stderr ? stderr : error);
    }

    return { result, error, stdout, stderr }
}

/**
 * 合并分支
 */
function mergeM(cwd) {

    let { branch } = getLocalBranch(cwd);

    if (branch.startsWith('D')) {

        checkoutToM(cwd)

    }

    let params = ['merge', 'D' + branch.substr(1)];

    let { result, error, stdout, stderr } = spawnSync('git', params, cwd);

    if (result) {

        message.info('合并分支 git ' + params.join(' '));

        log(1, '合并分支 git ' + params.join(' '));

    } else {

        message.error(stderr ? stderr : error);

    }

    return { result, error, stdout, stderr }

}

/**
 * 切换分支M
 */
function checkoutToM(cwd) {

    let { branch } = getLocalBranch(cwd);

    if (!branch.startsWith('D')) {

        message.error('请使用开发分支 Dxxx');

        return { result: false, error: '请使用开发分支 Dxxx', stdout: '请使用开发分支 Dxxx', stderr: '请使用开发分支 Dxxx' }

    }

    let params = ['checkout', 'M' + branch.substr(1)];

    let { result, error, stdout, stderr } = execSync('git '+ params.join(' '), cwd);

    if (result) {

        message.info('切换分支至M git ' + params.join(' '));

        log(1, '切换分支至M git ' + params.join(' '));

    } else {

        message.error(stderr ? stderr : error);

    }

    return { result, error, stdout, stderr }
}

/**
 * 切换分支D
 */
function checkoutToD(cwd) {

    let { branch } = getLocalBranch(cwd);

    if (!branch.startsWith('M')) {

        message.error('请使用生产分支 Mxxx');

        return { result: false, error: '请使用生产分支 Mxxx', stdout: '请使用生产分支 Mxxx', stderr: '请使用开发分支 Dxxx' }

    }

    let params = ['checkout', 'D' + branch.substr(1)];

    let { result, error, stdout, stderr } = execSync('git '+ params.join(' '), cwd);

    if (result) {

        message.info('切换分支至D git ' + params.join(' '));

        log(1, '切换分支至D git ' + params.join(' '));

    } else {

        message.error(stderr ? stderr : error);

    }

    return { result, error, stdout, stderr }
}

/**
 * 创建M分支
 */
function createMBranch(cwd) {

    let { branch } = getLocalBranch(cwd);

    if (branch.startsWith('M')) {

        message.error('请使用生产分支 Dxxx');

        return { result: false, error: '请使用生产分支 Dxxx', stdout: '请使用生产分支 Dxxx', stderr: '请使用生产分支 Dxxx' }

    }

    let params = ['branch', 'M' + branch.substr(1)];

    let { result, error, stdout, stderr } = spawnSync('git', params, cwd);

    if (result) {

        message.info('创建M分支 git ' + params.join(' '));

        log(1, '创建M分支 git ' + params.join(' '));

    } else {

        message.error(stderr ? stderr : error);

    }

    return { result, error, stdout, stderr }

}
module.exports = {
    check,
    gitInfo,
    push,
    add,
    commit,
    mergeM,
    checkoutToM,
    checkoutToD,
    pushTag,
    getLocalBranch,
    write,
    checkStatus,
    pull,
    createMBranch,
    checkVersionTag
}
